/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import rebound from "./rebound";

function springSystem_Test() {
    let springSystem;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        springSystem = new rebound.SpringSystem();
    }
    let endTime = Date.now();
    let spring = springSystem.createSpring();
    spring=springSystem.createSpring();
    spring.setSpringConfig(rebound.SpringConfig.DEFAULT_ORIGAMI_SPRING_CONFIG);
    spring.addListener({
        onSpringUpdate: function(spring) {
            // var val = spring.getCurrentValue();
            //Use Spring val to Process/Animate
            // print(val)
        },
        onSpringEndStateChange: function(spring){
            // var val = spring.getCurrentValue();
            //Use Spring val to Process/Animate
            // print(val)
        }
    });
    spring.setEndValue(1);
    print(`rebound_SpringSystem: ${endTime - startTime} ms`);

}

function createSpring_Test() {
    let spring;
    let springSystem = new rebound.SpringSystem();
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        spring = springSystem.createSpring();
    }
    let endTime = Date.now();
    spring.setSpringConfig(rebound.SpringConfig.DEFAULT_ORIGAMI_SPRING_CONFIG);
    spring.addListener({
        onSpringUpdate: function(spring) {
            // var val = spring.getCurrentValue();
            //Use Spring val to Process/Animate
            // print(val)
        },
        onSpringEndStateChange: function(spring){
            // var val = spring.getCurrentValue();
            //Use Spring val to Process/Animate
            // print(val)
        }
    });
    spring.setEndValue(1);
    print(`rebound_createSpring: ${endTime - startTime} ms`);

}

function createSpringWithBouncinessAndSpeed_Test() {
    let spring;
    let springSystem = new rebound.SpringSystem();
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        spring = springSystem.createSpringWithBouncinessAndSpeed(10, 10);
    }
    let endTime = Date.now();
    if ((spring.getSpringConfig().tension >= 0 && spring.getSpringConfig().friction >= 0) == false) {
        throw new Error('createSpringWithBouncinessAndSpeed failed');
    }
    print(`rebound_createSpringWithBouncinessAndSpeed: ${endTime - startTime} ms`);
}

function createSpringWithConfig_Test() {
    let spring;
    let springSystem = new rebound.SpringSystem();
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        spring = springSystem.createSpringWithConfig(rebound.SpringConfig.DEFAULT_ORIGAMI_SPRING_CONFIG);
    }
    let endTime = Date.now();
    if (spring == undefined) {
        throw new Error('createSpringWithConfig failed');
    }
    print(`rebound_createSpringWithConfig: ${endTime - startTime} ms`);
} 

function getIsIdle_Test() {
    let springSystem = new rebound.SpringSystem();
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 10000000; i++) { 
        result = springSystem.getIsIdle()
    }
    let endTime = Date.now();
    if (result == false) {
        throw new Error('getIsIdle failed');
    }
    print(`rebound_getIsIdle: ${endTime - startTime} ms`);
}

function getSpringById_Test() {
    let springSystem = new rebound.SpringSystem();
    let spring = springSystem.createSpringWithBouncinessAndSpeed(10, 10);
    let idStr = spring.getId();
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 10000000; i++) { 
        result = springSystem.getSpringById(idStr)
    }
    let endTime = Date.now();
    if (result == undefined) {
        throw new Error('getSpringById failed');
    }
    print(`rebound_getSpringById: ${endTime - startTime} ms`);
}

function getAllSprings_Test() {
    let springSystem = new rebound.SpringSystem();
    let spring = springSystem.createSpring(10, 10);
    spring.addListener({
      onSpringUpdate: (spring) => {
      }
    })
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        result = springSystem.getAllSprings();
    }
    let endTime = Date.now();
    if (result.length != 1) {
        throw new Error('getAllSprings failed');
    }
    print(`rebound_getAllSprings: ${endTime - startTime} ms`);    
}

function registerSpring_Test() {
    let springSystem = new rebound.SpringSystem();
    let spring = new rebound.Spring(springSystem);
    spring.setSpringConfig(rebound.SpringConfig.DEFAULT_ORIGAMI_SPRING_CONFIG);
    spring.addListener({
      onSpringUpdate: (spring) => {
      }
    })
    if (springSystem.getAllSprings().length != 0) {
        throw new Error('registerSpring failed');
    }
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        springSystem.registerSpring(spring);
    }
    let endTime = Date.now();
    if (springSystem.getAllSprings().length != 1) {
        throw new Error('registerSpring failed');
    }
    print(`rebound_registerSpring: ${endTime - startTime} ms`);    
}

function deregisterSpring_Test() {
    let springSystem = new rebound.SpringSystem();
    let spring = new rebound.Spring(springSystem);
    spring.setSpringConfig(rebound.SpringConfig.DEFAULT_ORIGAMI_SPRING_CONFIG);
    spring.addListener({
      onSpringUpdate: (spring) => {
      }
    })
    springSystem.registerSpring(spring);
    if (springSystem.getAllSprings().length != 1) {
        throw new Error('deregisterSpring failed');
    }
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        springSystem.deregisterSpring(spring);
    }
    let endTime = Date.now();
    if (springSystem.getAllSprings().length != 0) {
        throw new Error('deregisterSpring failed');
    }
    print(`rebound_deregisterSpring: ${endTime - startTime} ms`);    

}

function loop_Test() {
    let springSystem = new rebound.SpringSystem();
    let spring = springSystem.createSpring(10, 10);
    spring.addListener({
      onSpringUpdate: (spring) => {
      },
      onBeforeIntegrate:(spring) => {
      }
    })
    let nowTime = new Date().getTime();
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        springSystem.loop(nowTime + 20);
    }
    let endTime = Date.now();
    if (springSystem._isIdle == false) {
        throw new Error('loop failed');
    }
    print(`rebound_loop: ${endTime - startTime} ms`);    
}

function activateSpring_Test() {
    let springsystem = new rebound.SpringSystem();
    let spring = new rebound.Spring(springsystem);
    spring.setSpringConfig(rebound.SpringConfig.DEFAULT_ORIGAMI_SPRING_CONFIG);
    spring.addListener({
      onSpringUpdate: (spring) => {
      }
    })
    let startTime = Date.now();
    for (let i = 0; i < 1; i++) { 
        springsystem.activateSpring(spring);
    }
    let endTime = Date.now();
    if (springsystem.getIsIdle() == false) {
        throw new Error('activateSpring failed');
    }
    print(`rebound_activateSpring: ${endTime - startTime} ms`);    
}

function spring_Test() {
    let springSystem = new rebound.SpringSystem();
    let spring;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        spring = new rebound.Spring(springSystem);
    }
    let endTime = Date.now();
    spring.setSpringConfig(rebound.SpringConfig.DEFAULT_ORIGAMI_SPRING_CONFIG);
    spring.addListener({
      onSpringUpdate: (spring) => {
      }
    })
    springSystem.registerSpring(spring);
    if (springSystem.getAllSprings().length != 1) {
        throw new Error('activateSpring failed');
    }
    print(`rebound_Spring: ${endTime - startTime} ms`);    

}

function destroy_Test() {
    let springSystem = new rebound.SpringSystem();
    let spring = springSystem.createSpring(10, 10);
    spring.addListener({
      onSpringUpdate: (spring) => {
      }
    })
    if (spring.getListeners().length == 0) {
        throw new Error('activateSpring failed');
    }
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        spring.destroy();
    }
    let endTime = Date.now();
    if (spring.getListeners().length != 0) {
        throw new Error('destroy failed');
    }
    print(`rebound_destroy: ${endTime - startTime} ms`);    
}

function getId_Test() {
    let springSystem = new rebound.SpringSystem();
    let spring = springSystem.createSpring(10, 10);
    spring.addListener({
      onSpringUpdate: (spring) => {
      }
    })
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 10000000; i++) { 
        result = spring.getId();
    }
    let endTime = Date.now();
    if (springSystem.getSpringById(result) === undefined) {
        throw new Error('getId failed');
    }
    print(`rebound_getId: ${endTime - startTime} ms`);    
}

function getSpringConfig_Test() {
    let spring = new rebound.SpringSystem().createSpringWithBouncinessAndSpeed(10, 10);
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 10000000; i++) { 
        result = spring.getSpringConfig();
    }
    let endTime = Date.now();
    if ((spring.getSpringConfig().tension >= 0 && spring.getSpringConfig().friction >= 0) == false) {
        throw new Error('getSpringConfig failed');
    }
    print(`rebound_getSpringConfig: ${endTime - startTime} ms`);    
}

function getCurrentValue_Test() {
    let springSystem = new rebound.SpringSystem();
    let spring = new rebound.Spring(springSystem);
    spring.addListener({
        onSpringUpdate: (spring) => {
        }      
    })
    spring.setCurrentValue(10, false);
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = spring.getCurrentValue();
    }
    let endTime = Date.now();  
    if (result != 10) {
        throw new Error('getCurrentValue failed');
    }
    print(`rebound_getCurrentValue: ${endTime - startTime} ms`);  
}

function setCurrentValue_Test() {
    let springSystem = new rebound.SpringSystem();
    let spring = new rebound.Spring(springSystem);
    spring.addListener({
        onSpringUpdate: (spring) => {
        }      
    })    
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 10; i++) { 
        result = spring.setCurrentValue(10, false);
    }
    let endTime = Date.now();  
    if (result.getCurrentValue() != 10) {
        throw new Error('setCurrentValue failed');
    }
    print(`rebound_setCurrentValue: ${endTime - startTime} ms`);  
}

function getStartValue_Test() {
    let springSystem = new rebound.SpringSystem();
    let spring = new rebound.Spring(springSystem);
    spring.addListener({
        onSpringUpdate: (spring) => {
        }      
    })
    spring.setCurrentValue(10, false);
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = spring.getStartValue();
    }
    let endTime = Date.now();  
    if (result != 10) {
        throw new Error('getStartValue failed');
    }
    print(`rebound_getStartValue: ${endTime - startTime} ms`);  
}

function getCurrentDisplacementDistance_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = spring.getCurrentDisplacementDistance();
    }
    let endTime = Date.now(); 
    if (result == undefined) {
        throw new Error('getCurrentDisplacementDistance failed');
    }
    print(`rebound_getCurrentDisplacementDistance: ${endTime - startTime} ms`);  
}

function getEndValue_Test() {
    let springSystem = new rebound.SpringSystem();
    let spring = new rebound.Spring(springSystem);
    spring.addListener({
      onSpringUpdate: (spring) => {
      }
    })
    spring.setEndValue(1.0);
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = spring.getEndValue();
    }
    let endTime = Date.now(); 
    if (result != 1.0) {
        throw new Error('getEndValue failed');
    }
    print(`rebound_getEndValue: ${endTime - startTime} ms`);  
}

function setEndValue_Test() {
    let springSystem = new rebound.SpringSystem();
    let spring = new rebound.Spring(springSystem);
    spring.addListener({
      onSpringUpdate: (spring) => {
      }
    })
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1; i++) { 
        result = spring.setEndValue(1.0);
    }
    let endTime = Date.now(); 
    if (result.getEndValue() != 1.0) {
        throw new Error('setEndValue failed');
    }
    print(`rebound_setEndValue: ${endTime - startTime} ms`);  
}

function getVelocity_Test() {
    let springsystem = new rebound.SpringSystem();
    let spring = new rebound.Spring(springsystem);
    spring.setVelocity(15);
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = spring.getVelocity();
    }
    let endTime = Date.now(); 
    if (result != 15) {
        throw new Error('getVelocity failed');
    }
    print(`rebound_getVelocity: ${endTime - startTime} ms`);  
}

function setVelocity_Test() {
    let springsystem = new rebound.SpringSystem();
    let spring = new rebound.Spring(springsystem);
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        result = spring.setVelocity(15);
    }
    let endTime = Date.now(); 
    if (result.getVelocity() != 15) {
        throw new Error('setVelocity failed');
    }
    print(`rebound_setVelocity: ${endTime - startTime} ms`);  
}

function getRestSpeedThreshold_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = spring.getRestSpeedThreshold();
    }
    let endTime = Date.now(); 
    if (result != 0.005) {
        throw new Error('getRestSpeedThreshold failed');
    }
    print(`rebound_getRestSpeedThreshold: ${endTime - startTime} ms`);  
}

function setRestSpeedThreshold_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    if (spring.getRestSpeedThreshold() != 0.005) {
        throw new Error('getRestSpeedThreshold failed');
    }
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = spring.setRestSpeedThreshold(1);
    }
    let endTime = Date.now(); 
    if (result.getRestSpeedThreshold() != 1) {
        throw new Error('setRestSpeedThreshold failed');
    }
    print(`rebound_setRestSpeedThreshold: ${endTime - startTime} ms`);  
}

function getRestDisplacementThreshold_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    spring.addListener({
      onSpringUpdate: (spring) => {
      }
    })
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = spring.getRestDisplacementThreshold();
    }
    let endTime = Date.now(); 
    if (result != 0.005) {
        throw new Error('getRestDisplacementThreshold failed');
    }
    print(`rebound_getRestDisplacementThreshold: ${endTime - startTime} ms`);  
}

function isOvershootClampingEnabled_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    spring.setOvershootClampingEnabled(true);
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 10000000; i++) { 
        result = spring.isOvershootClampingEnabled();
    }
    let endTime = Date.now(); 
    if (result != true) {
        throw new Error('isOvershootClampingEnabled failed');
    }
    print(`rebound_isOvershootClampingEnabled: ${endTime - startTime} ms`);  
}

function setOvershootClampingEnabled_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = spring.setOvershootClampingEnabled(true);
    }
    let endTime = Date.now(); 
    if (result.isOvershootClampingEnabled() != true) {
        throw new Error('setOvershootClampingEnabled failed');
    }
    print(`rebound_setOvershootClampingEnabled: ${endTime - startTime} ms`);  
}

function isOvershooting_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = spring.isOvershooting();
    }
    let endTime = Date.now(); 
    if (result == true) {
        throw new Error('isOvershooting failed');
    }
    print(`rebound_isOvershooting: ${endTime - startTime} ms`);  
}

function isAtRest_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    spring.setAtRest()
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = spring.isAtRest();
    }
    let endTime = Date.now(); 
    if (result != true) {
        throw new Error('isAtRest failed');
    }
    print(`rebound_isAtRest: ${endTime - startTime} ms`);  
}

function setAtRest_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = spring.setAtRest();
    }
    let endTime = Date.now(); 
    if (result.isAtRest() != true) {
        throw new Error('setAtRest failed');
    }
    print(`rebound_setAtRest: ${endTime - startTime} ms`);  
}

function addListener_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        result = spring.addListener({
            onSpringUpdate: (spring) => {
            }
        })
    }
    let endTime = Date.now(); 
    if (result.getListeners().length != 100000) {
        throw new Error('addListener failed');
    }
    print(`rebound_addListener: ${endTime - startTime} ms`);  
}

function removeListener_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    let springUpdate = {
      onSpringUpdate: (spring) => {
      }
    }
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = spring.removeListener(springUpdate);
    }
    let endTime = Date.now(); 
    if (result.getListeners().length != 0) {
        throw new Error('removeListener failed');
    }
    print(`rebound_removeListener: ${endTime - startTime} ms`);  
}

function removeAllListeners_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    spring.addListener({
        onSpringUpdate: (spring) => {
        }
    })
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        result = spring.removeAllListeners();
    }
    let endTime = Date.now(); 
    if (result.getListeners().length != 0) {
        throw new Error('removeAllListeners failed');
    }
    print(`rebound_removeAllListeners: ${endTime - startTime} ms`);
}

function onSpringEndStateChange_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        spring.addListener({
            onSpringEndStateChange: (spring) => {
            }
        })
    }
    let endTime = Date.now(); 
    print(`rebound_onSpringEndStateChange: ${endTime - startTime} ms`);  
}

function onBeforeIntegrate_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        spring.addListener({
            onBeforeIntegrate: (spring) => {
            }
        })
    }
    let endTime = Date.now(); 
    print(`rebound_onBeforeIntegrate: ${endTime - startTime} ms`);  
}

function onAfterIntegrate_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        spring.addListener({
            onAfterIntegrate: (spring) => {
            }
        })
    }
    let endTime = Date.now(); 
    print(`rebound_onAfterIntegrate: ${endTime - startTime} ms`);  
}

function onSpringActivate_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        spring.addListener({
            onSpringActivate: (spring) => {
            }
        })
    }
    let endTime = Date.now(); 
    print(`rebound_onSpringActivate: ${endTime - startTime} ms`);  
}

function onSpringUpdate_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        spring.addListener({
            onSpringUpdate: (spring) => {
            }
        })
    }
    let endTime = Date.now(); 
    print(`rebound_onSpringUpdate: ${endTime - startTime} ms`);  
}

function onSpringAtRest_Test() {
    let spring = new rebound.SpringSystem().createSpring(10, 10);
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        spring.addListener({
            onSpringAtRest: (spring) => {
            }
        })
    }
    let endTime = Date.now(); 
    print(`rebound_onSpringAtRest: ${endTime - startTime} ms`);  
}

function SpringConfig_Test() {
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 10000000; i++) { 
        result = rebound.SpringConfig.DEFAULT_ORIGAMI_SPRING_CONFIG;
    }
    let endTime = Date.now(); 
    let spring = new rebound.SpringSystem().createSpringWithConfig(result);
    if (spring == undefined) {
        throw new Error('SpringConfig failed');
    }
    print(`rebound_SpringConfig: ${endTime - startTime} ms`);
}

function fromOrigamiTensionAndFriction_Test() {
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        result = rebound.SpringConfig.fromOrigamiTensionAndFriction(10, 10);
    }
    let endTime = Date.now(); 
    if ((result.tension === undefined || result.friction === undefined) == true) {
        throw new Error('fromOrigamiTensionAndFriction failed');
    }
    print(`rebound_fromOrigamiTensionAndFriction: ${endTime - startTime} ms`);
}

function fromBouncinessAndSpeed_Test() {
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        result = rebound.SpringConfig.fromBouncinessAndSpeed(10, 10);
    }
    let endTime = Date.now(); 
    if ((result.tension === undefined || result.friction === undefined) == true) {
        throw new Error('fromBouncinessAndSpeed failed');
    }
    print(`rebound_fromBouncinessAndSpeed: ${endTime - startTime} ms`);
}

function coastingConfigWithOrigamiFriction_Test() {
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        result = rebound.SpringConfig.coastingConfigWithOrigamiFriction(10, 10);
    }
    let endTime = Date.now(); 
    if ((result.tension === undefined || result.friction === undefined) == true) {
        throw new Error('coastingConfigWithOrigamiFriction failed');
    }
    print(`rebound_coastingConfigWithOrigamiFriction: ${endTime - startTime} ms`);
}

function AnimationLooper_Test() {
    let spring = new rebound.SpringSystem().createSpring();
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = new rebound.AnimationLooper();
    }
    let endTime = Date.now(); 
    let springSystem = new rebound.SpringSystem(result);
    springSystem.activateSpring(spring.getId())
    springSystem.loop(20)
    if (springSystem._idleSpringIndices.length != 0) {
        throw new Error('AnimationLooper failed');
    }
    print(`rebound_AnimationLooper: ${endTime - startTime} ms`);
}

function SimulationLooper_Test() {
    let spring = new rebound.SpringSystem().createSpring();
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        result = new rebound.SimulationLooper();
    }
    let endTime = Date.now(); 
    let springSystem = new rebound.SpringSystem(result);
    springSystem.activateSpring(spring.getId())
    springSystem.loop(20)
    if (springSystem._idleSpringIndices.length != 0) {
        throw new Error('SimulationLooper failed');
    }
    print(`rebound_SimulationLooper: ${endTime - startTime} ms`);
}

function SteppingSimulationLooper_Test() {
    let spring = new rebound.SpringSystem().createSpring();
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        result = new rebound.SteppingSimulationLooper();
    }
    let endTime = Date.now(); 
    let springSystem = new rebound.SpringSystem(result);
    springSystem.activateSpring(spring.getId())
    springSystem.loop(20)
    if (springSystem._idleSpringIndices.length != 0) {
        throw new Error('SteppingSimulationLooper failed');
    }
    print(`rebound_SteppingSimulationLooper: ${endTime - startTime} ms`);
}

function tensionFromOrigamiValue_Test() {
    let expected = 197.62;
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 10000000; i++) { 
        result = rebound.OrigamiValueConverter.tensionFromOrigamiValue(31);
    }
    let endTime = Date.now(); 
    if (result != expected) {
        throw new Error('tensionFromOrigamiValue failed');
    }
    print(`rebound_tensionFromOrigamiValue: ${endTime - startTime} ms`);
}

function origamiValueFromTension_Test() {
    let expected = 31;
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 10000000; i++) { 
        result = rebound.OrigamiValueConverter.origamiValueFromTension(197.62);
    }
    let endTime = Date.now(); 
    if (result != expected) {
        throw new Error('origamiValueFromTension failed');
    }
    print(`rebound_origamiValueFromTension: ${endTime - startTime} ms`);
}

function frictionFromOrigamiValue_Test() {
    let expected = 28;
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 10000000; i++) { 
        result = rebound.OrigamiValueConverter.frictionFromOrigamiValue(9);
    }
    let endTime = Date.now(); 
    if (result != expected) {
        throw new Error('frictionFromOrigamiValue failed');
    }
    print(`rebound_frictionFromOrigamiValue: ${endTime - startTime} ms`);
}

function origamiFromFriction_Test() {
    let expected = 9;
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 10000000; i++) { 
        result = rebound.OrigamiValueConverter.origamiFromFriction(28);
    }
    let endTime = Date.now(); 
    if (result != expected) {
        throw new Error('origamiFromFriction failed');
    }
    print(`rebound_origamiFromFriction: ${endTime - startTime} ms`);
}

function mapValueInRange_Test() {
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 10000000; i++) { 
        result = rebound.MathUtil.mapValueInRange(10, 1, 100, 0, 1);
    }
    let endTime = Date.now(); 
    if (result.toFixed(1) != 0.1) {
        throw new Error('mapValueInRange failed');
    }
    print(`rebound_mapValueInRange: ${endTime - startTime} ms`);
}

function interpolateColor_Test() {
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        result = rebound.MathUtil.interpolateColor(10, "#AAA501", "#FFA501", 10, 100, true);
    }
    let endTime = Date.now(); 
    if (result != "rgb(170,165,1)") {
        throw new Error('interpolateColor failed');
    }
    print(`rebound_interpolateColor: ${endTime - startTime} ms`);
}

function degreesToRadians_Test() {
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = rebound.MathUtil.degreesToRadians(180);
    }
    let endTime = Date.now(); 
    if (result != Math.PI) {
        throw new Error('degreesToRadians failed');
    }
    print(`rebound_degreesToRadians: ${endTime - startTime} ms`);
}

function radiansToDegrees_Test() {
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = rebound.MathUtil.radiansToDegrees(Math.PI);
    }
    let endTime = Date.now(); 
    if (result != 180) {
        throw new Error('radiansToDegrees failed');
    }
    print(`rebound_radiansToDegrees: ${endTime - startTime} ms`);
}

function bind_Test() {
    let num = 5;
    let func = ()=>{  num = num - 1  };
    let context = { name : '张三'};
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        result = rebound.util.bind(func, context);
    }
    let endTime = Date.now(); 
    result();
    if (num != 4) {
        throw new Error('bind failed');
    }
    print(`rebound_bind: ${endTime - startTime} ms`);
}

function extend_Test() {
    let source = {
        a: 55, b: 20
    };
    let target = {
        a: 10, c: 30, d: 20
    };
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        rebound.util.extend(target, source);
    }
    let endTime = Date.now(); 
    if (target.a != 55) {
        throw new Error('extend failed');
    }
    print(`rebound_extend: ${endTime - startTime} ms`);
}

function removeFirst_Test() {
    let beasts = ['ant', 'bison', 'camel', 'duck', 'bison'];
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        rebound.util.removeFirst(beasts, "bison");
    }
    let endTime = Date.now(); 
    if (beasts.indexOf('bison') != -1) {
        throw new Error('removeFirst failed');
    }
    print(`rebound_removeFirst: ${endTime - startTime} ms`);
}

function hexToRGB_Test() {
    let hexcolor = "#FFA501";
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 1000000; i++) { 
        result = rebound.util.hexToRGB(hexcolor);
    }
    let endTime = Date.now(); 
    if ((result.r == 255 && result.g == 165 && result.b == 1) != true) {
        throw new Error('hexToRGB failed');
    }
    print(`rebound_hexToRGB: ${endTime - startTime} ms`);
}

function rgbToHex_Test() {
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        result = rebound.util.rgbToHex(255, 165, 1);
    }
    let endTime = Date.now(); 
    if (result.toUpperCase() != "#FFA501") {
        throw new Error('rgbToHex failed');
    }
    print(`rebound_rgbToHex: ${endTime - startTime} ms`);
}

function BouncyConversion_Test() {
    let result;
    let startTime = Date.now();
    for (let i = 0; i < 100000; i++) { 
        result = new rebound.BouncyConversion(10, 20);
    }
    let endTime = Date.now(); 
    if (result.normalize(10, 1, 100) != 0.09090909090909091) {
        throw new Error('BouncyConversion failed');
    }
    print(`rebound_BouncyConversion: ${endTime - startTime} ms`);
}

springSystem_Test();
createSpring_Test();
createSpringWithBouncinessAndSpeed_Test();
createSpringWithConfig_Test();
getIsIdle_Test();
getSpringById_Test();
getAllSprings_Test();
registerSpring_Test();
deregisterSpring_Test();
loop_Test();
activateSpring_Test();
spring_Test();
destroy_Test();
getId_Test();
getSpringConfig_Test();
getCurrentValue_Test();
setCurrentValue_Test();
getStartValue_Test();
getCurrentDisplacementDistance_Test();
getEndValue_Test();
setEndValue_Test();
getVelocity_Test();
setVelocity_Test();
getRestSpeedThreshold_Test();
setRestSpeedThreshold_Test();
getRestDisplacementThreshold_Test();
isOvershootClampingEnabled_Test();
setOvershootClampingEnabled_Test();
isOvershooting_Test();
isAtRest_Test();
setAtRest_Test();
addListener_Test();
removeListener_Test();
removeAllListeners_Test();
onSpringEndStateChange_Test();
onBeforeIntegrate_Test();
onAfterIntegrate_Test();
onSpringActivate_Test();
onSpringUpdate_Test();
onSpringAtRest_Test();
SpringConfig_Test();
fromOrigamiTensionAndFriction_Test();
fromBouncinessAndSpeed_Test();
coastingConfigWithOrigamiFriction_Test();
AnimationLooper_Test();
SimulationLooper_Test();
SteppingSimulationLooper_Test();
tensionFromOrigamiValue_Test();
origamiValueFromTension_Test();
frictionFromOrigamiValue_Test();
origamiFromFriction_Test();
mapValueInRange_Test();
interpolateColor_Test();
degreesToRadians_Test();
radiansToDegrees_Test();
bind_Test();
extend_Test();
removeFirst_Test();
hexToRGB_Test();
rgbToHex_Test();
BouncyConversion_Test();
